#include "shared.h"

uint8 cart_ram[0x10000] CACHEALIGN;
uint32 sram_start;
uint32 sram_end;

int sram_present;
int sram_active;

int rom_size;

void sram_init()
{
	/* Check the cart header */
	if(READ_WORD(cart_rom, 0x0001B0) == 0x5241)
	{
		sram_present = 1;
		sram_start = READ_LONG(cart_rom, 0x0001B4) & 0xFFFFFF;
		sram_end = READ_LONG(cart_rom, 0x0001B8) & 0xFFFFFF;
	}
	else
	{
		/* No SRAM in the header, so assume it's 64K (for S3K) */
		sram_present = 0;
		sram_start = 0x200000;
		sram_end = 0x20FFFF;
	}

	/* Try to load saved SRAM */
	sram_load();
}

void sram_reset()
{
	/* If the ROM is small enough, enable SRAM by default */
	if((sram_present) && (rom_size <= 0x200000))
		sram_on();
	else
		sram_off();
}

/* Activate SRAM area */
void sram_on()
{
	sram_present = 1;
	sram_active = 1;
}

/* Deactivate SRAM area */
void sram_off()
{
	sram_active = 0;
}

/* Try to load SRAM */
void sram_load()
{
	uint16 addr_first, addr_last;
	uint8 addr_mask;
	int i;

	memset(cart_ram, 0, sizeof(cart_ram));

	// Open file
	if(!sram_read_open())
		return;

	printf("Successfully opened SRAM\n");

	// Read header
	sram_start = sram_read_uint32();
	sram_end = sram_read_uint32();
	addr_first = sram_read_uint16();
	addr_last = sram_read_uint16();
	addr_mask = sram_read_uint8();

	// Read data
	for(i = addr_first; i <= addr_last; i++)
	{
		if(i & 0x01)
		{
			if(addr_mask & 0x02)
				cart_ram[i] = sram_read_uint8();
		}
		else
		{
			if(addr_mask & 0x01)
				cart_ram[i] = sram_read_uint8();
		}
	}

	// Close file
	sram_read_close();

	// We do, in fact, have SRAM
	if(!sram_present)
		sram_present = 1;
}

/* Try to save SRAM */
void sram_save()
{
	int addr_odd, addr_even;
	uint16 addr_first, addr_last;
	uint8 addr_mask;
	int i;

	// Don't bother if we don't have SRAM
	if(!sram_present)
		return;

	// Work out what data needs to be stored
	addr_first = 0xFFFF;
	addr_last = 0;
	addr_odd = addr_even = 0;
	for(i = 0; i < 0x10000; i++)
	{
		if(cart_ram[i])
		{
			if(addr_first > i)
				addr_first = i;
			if(addr_last < i)
				addr_last = i;
			if(i & 0x01)
				addr_odd = 1;
			else
				addr_even = 1;
		}
	}
	addr_mask = 0;
	if(addr_even)
		addr_mask |= 0x01;
	if(addr_odd)
		addr_mask |= 0x02;

	// If nothing has been written, do not bother saving
	if(!addr_mask)
		return;

	// Create file
	if(!sram_write_open())
		return;

	// Write header
	sram_write_uint32(sram_start);
	sram_write_uint32(sram_end);
	sram_write_uint16(addr_first);
	sram_write_uint16(addr_last);
	sram_write_uint8(addr_mask);

	// Write data
	for(i = addr_first; i <= addr_last; i++)
	{
		if(i & 0x01)
		{
			if(addr_mask & 0x02)
				sram_write_uint8(cart_ram[i]);
		}
		else
		{
			if(addr_mask & 0x01)
				sram_write_uint8(cart_ram[i]);
		}
	}

	// Close file
	sram_write_close();
}
